import random
import uuid

import werkzeug
from flask import Blueprint, render_template, request, jsonify, flash, redirect, url_for, abort, Response
from Config import db
from models.my_model import Post, User, R, UserRo
from sqlalchemy import func

page_user = Blueprint("user", __name__)

from flask_login import login_user, logout_user, current_user, AnonymousUserMixin, \
    login_required  # q80：此处引入了当前登录对象 current_user


@page_user.route("/user/setting", methods=["GET"])
@login_required
def user_setting() -> [str, Response]:
    username = current_user.username
    oldPasswordError = ""
    newPasswordError = ""
    cpwdError = ""
    return render_template(
        "user_setting.html",
        username=username,
        oldPasswordError=oldPasswordError,
        newPasswordError=newPasswordError,
        cpwdError=cpwdError
    )


# @page_user.route("/user/profile/<int:id>", methods=["GET"])
# def user_profile(id: int) -> [str, Response]:
#     return jsonify(
#         R(200, f"userid -- {id} -- profile").define()
#     )


@page_user.route("/register", methods=["GET", "POST"])
def register() -> [str, Response]:
    if request.method == "GET":
        userMsg: dict = {
            "usernameMsg": None,
            "passwordMsg": None,
            "emailMsg": None
        }
        user: UserRo = None
        return render_template(
            "user_register.html",
            userMsg=userMsg,
            user=user
        )
    elif request.method == "POST":
        request_json = request.form
        password: str = ""
        username: str = ""
        email: str = ""
        try:
            email: str = request_json["email"]
            password: str = request_json["password"]
            username: str = request_json["username"]
        except Exception as e:
            print(e)
        userRo: UserRo = UserRo(username, password, email)
        if not username or not password or username == "" or password == "":
            # return jsonify(R(4004, "username or password should not be blank").define())
            return render_template("error_with_msg.html", msg="4004 - 用户名或密码为空，请检查")
        if not email or email == "":
            # return jsonify(R(4005, "email should not be blank").define())
            return render_template("error_with_msg.html", msg="4005 - 邮箱为空，请检查")
        if len(password) > 16:
            # return jsonify(R(4006, "password too long, should not longer than 16 bit").define())
            return render_template("error_with_msg.html", msg="4006 - 密码长度过长，请控制在16位以内")

        user: list = User.query.filter(User.username == username).all()
        if len(user) >= 1:
            # return jsonify(R(4010, "username be registered").define())
            return render_template("error_with_msg.html", msg="4010 - 用户名已被注册，请重新选用")
        user: list = User.query.filter(User.email == email).all()
        if len(user) >= 1:
            # return jsonify(R(4011, "email be registered").define())
            return render_template("error_with_msg.html", msg="4011 - 邮箱已被注册，请重新选用")
        rint: int = random.randint(1, 1000)
        user: User = User(
            username=username,
            email=email,
            type=1,
            status=1,
            activation_code=uuid.uuid1(),
            header_url=f"http://images.nowcoder.com/head/{rint}t.png"
        )
        user.set_password(password)  # 设置用户password
        session: db.session = db.session()
        # db.create_all()
        session.add(user)
        session.commit()
        session.close()
        # return jsonify(R(code=200, msg=f"user {username} registered").define())
        return render_template("with_msg.html", msg=f"用户 {username} 注册成功！")
    else:
        # return jsonify(R(code=400, msg="assess denied").define())
        return render_template("error_with_msg.html", msg="拒绝访问")


@page_user.route("/logout", methods=["GET", "POST"])
@login_required
def logout() -> [str, Response]:
    cu: User = current_user  # q81: 此处获取了当前登录的User对象
    if current_user.is_anonymous == True:
        # return jsonify(R(code=400, msg=f"no user logged in").define())
        return render_template("error_with_msg.html", msg="400 - 无登录用户")
    logout_user()
    # return jsonify(R(code=200, msg=f"{un} logged out").define())
    return render_template("with_msg.html", msg=f"用户已退出")


@page_user.route("/login", methods=["GET", "POST"])
def login() -> [str, Response]:
    if current_user.is_anonymous == False:  # q82: 此处检查是否存在已登录用户
        return render_template("with_msg.html", msg=f"{current_user.username}，欢迎！请勿重复登录")
    if request.method == "GET":
        userMsg: dict = {
            "usernameMsg": None,
            "passwordMsg": None,
            "codeMsg": None
        }
        return render_template(
            "user_login.html",
            userMsg=userMsg
        )
    elif request.method == "POST":
        request_json = request.form
        code: str = ""
        password: str = ""
        username: str = ""
        rememberMe: bool = False
        try:
            code: str = request_json["code"]
            password: str = request_json["password"]
            username: str = request_json["username"]
            rememberMe: bool = True if request_json["rememberMe"] else False
        except Exception as e:
            print(e)
        if not username or not password or username == "" or password == "":
            # return jsonify(R(400, "username or password should not be blank").define())
            return render_template("error_with_msg.html", msg="400 - 用户名或密码为空，请检查")

        #
        user: list = User.query.filter(User.username == username).all()
        if len(user) > 1:
            # return jsonify(R(500, "multi user exists, contact administrator").define())
            return render_template("error_with_msg.html", msg="500 - 存在多个同名用户，请联系管理员")
        if len(user) <= 0:
            # return jsonify(R(400, f"user {username} not found").define())
            return render_template("error_with_msg.html", msg=f"4020 - 用户 {username} 不存在，请检查用户名")
        user: User = user[0]
        if not user.validate_password(password):
            # return jsonify(R(400, f"user {user.username} validate failed (password)").define())
            return render_template("error_with_msg.html", msg=f"4021 - {username} 认证失败，请检查密码")
        login_user(user)

        data = {
            "code": code,
            "rememberMe": rememberMe,
            "username": username
        }

        # return jsonify(R(code=200, msg="logged in", data=data).define())
        return render_template("with_msg.html", msg=f"用户 {username} 登录成功！", target="/index")
    else:
        return render_template("error_with_msg.html", msg="拒绝访问")


@page_user.route("/user/reset_password", methods=["POST"])
@login_required
def reset_password() -> [str, Response]:
    cu: User = current_user
    username = cu.username
    oldPasswordError: str = "None"
    newPasswordError: str = None
    cpwdError: str = None

    request_json = request.form

    oldPassword: str = ""
    newPassword: str = ""
    confirm_password: str = ""
    try:
        oldPassword = request_json["oldPassword"]
        newPassword = request_json["newPassword"]
        confirm_password = request_json["confirm-password"]
    except Exception as e:
        print(e)
    if oldPassword == "" or not oldPassword:
        oldPasswordError = "原密码不能为空"
        newPasswordError = ""
        cpwdError = ""
        return render_template(
            "user_setting.html",
            username=username,
            oldPasswordError=oldPasswordError,
            newPasswordError=newPasswordError,
            cpwdError=cpwdError,
            oldPassword=oldPassword,
            newPassword=newPassword
        )
    if newPassword == "" or not newPassword:
        newPasswordError = "新密码不能为空"
        oldPasswordError = ""
        cpwdError = ""
        return render_template(
            "user_setting.html",
            username=username,
            oldPasswordError=oldPasswordError,
            newPasswordError=newPasswordError,
            cpwdError=cpwdError,
            oldPassword=oldPassword,
            newPassword=newPassword
        )
    if confirm_password == "" or not confirm_password:
        cpwdError = "确认密码不能为空"
        newPasswordError = ""
        oldPasswordError = ""
        return render_template(
            "user_setting.html",
            username=username,
            oldPasswordError=oldPasswordError,
            newPasswordError=newPasswordError,
            cpwdError=cpwdError,
            oldPassword=oldPassword,
            newPassword=newPassword
        )
    userAltering: list = db.session.query(User).filter_by(id=cu.id).all()
    if len(userAltering) == 0:
        abort(500)
    userAltering: User = userAltering[0]
    if not userAltering.validate_password(oldPassword):
        cpwdError = ""
        newPasswordError = ""
        oldPasswordError = "密码错误"
        return render_template(
            "user_setting.html",
            username=username,
            oldPasswordError=oldPasswordError,
            newPasswordError=newPasswordError,
            cpwdError=cpwdError
        )
    if newPassword != confirm_password:
        cpwdError = "确认密码与新密码不一致"
        newPasswordError = ""
        oldPasswordError = ""
        return render_template(
            "user_setting.html",
            username=username,
            oldPasswordError=oldPasswordError,
            newPasswordError=newPasswordError,
            cpwdError=cpwdError,
            oldPassword=oldPassword,
            newPassword=newPassword
        )

    userAltering.set_password(newPassword)
    db.session.merge(userAltering)
    db.session.commit()
    return render_template(
        "with_msg.html",
        msg=cu.username + " 密码修改成功",
        oldPasswordError=oldPasswordError,
        newPasswordError=newPasswordError,
        cpwdError=cpwdError
    )


def _query_username_by_id(id: int) -> str:
    user = User.query.filter(User.id == id).all()
    if len(user) > 1:
        raise Exception("存在多个用户")
    if len(user) == 0:
        raise Exception("用户不存在")
    user: User = user[0]
    username = user.username
    return username


@page_user.errorhandler(401)
def user_err_401(error):
    return render_template("error_with_msg.html", msg="拒绝访问", detail="您可能尚未登录或是权限不足")
